<template>
  <div class="min-h-screen py-8 px-4 sm:px-6 lg:px-8">
    <div class="max-w-7xl mx-auto">
      <!-- 页面标题 -->
      <div class="text-center mb-12">
        <h1 class="text-4xl font-bold mb-4 tech-text">Web Workers API</h1>
        <p class="text-gray-300 text-lg">
          后台线程处理，实现复杂计算而不阻塞主线程，提升应用性能
        </p>
      </div>

      <!-- 性能对比演示 -->
      <div class="tech-card mb-8">
        <h2 class="text-2xl font-semibold mb-6 text-white">性能对比演示</h2>
        
        <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
          <div class="bg-gray-800 rounded-lg p-6">
            <div class="flex items-center mb-4">
              <i class="i-carbon-cpu text-2xl text-blue-400 mr-3"></i>
              <h3 class="text-lg font-semibold text-white">主线程计算</h3>
            </div>
            <button
              @click="calculateOnMainThread"
              :disabled="isCalculating"
              class="tech-button w-full mb-4 disabled:opacity-50 disabled:cursor-not-allowed"
            >
              <i class="i-carbon-calculator mr-2"></i>
              {{ isCalculating ? '计算中...' : '计算斐波那契数列 (n=42)' }}
            </button>
            <div v-if="mainThreadResult !== null" class="space-y-2">
              <div class="text-green-400">
                <strong>结果:</strong> {{ mainThreadResult }}
              </div>
              <div class="text-gray-400 text-sm">
                <strong>耗时:</strong> {{ mainThreadTime }}ms
              </div>
            </div>
            <div class="mt-4 p-3 bg-red-900/30 border border-red-600 rounded">
              <p class="text-red-400 text-sm">
                <i class="i-carbon-warning mr-2"></i>
                计算期间UI会卡顿，无法交互
              </p>
            </div>
          </div>

          <div class="bg-gray-800 rounded-lg p-6">
            <div class="flex items-center mb-4">
              <i class="i-carbon-processor text-2xl text-green-400 mr-3"></i>
              <h3 class="text-lg font-semibold text-white">Web Worker 计算</h3>
            </div>
            <button
              @click="calculateWithWorker"
              :disabled="isWorkerCalculating"
              class="tech-button w-full mb-4 disabled:opacity-50 disabled:cursor-not-allowed"
            >
              <i class="i-carbon-cloud-data-ops mr-2"></i>
              {{ isWorkerCalculating ? '计算中...' : '使用 Worker 计算 (n=42)' }}
            </button>
            <div v-if="workerResult !== null" class="space-y-2">
              <div class="text-green-400">
                <strong>结果:</strong> {{ workerResult }}
              </div>
              <div class="text-gray-400 text-sm">
                <strong>耗时:</strong> {{ workerTime }}ms
              </div>
            </div>
            <div class="mt-4 p-3 bg-green-900/30 border border-green-600 rounded">
              <p class="text-green-400 text-sm">
                <i class="i-carbon-checkmark mr-2"></i>
                UI保持流畅，可以正常交互
              </p>
            </div>
          </div>
        </div>

        <!-- 交互测试 -->
        <div class="bg-gray-800 rounded-lg p-6">
          <h3 class="text-lg font-semibold text-white mb-3">测试UI响应性</h3>
          <p class="text-gray-400 text-sm mb-3">在计算过程中尝试拖动滑块，测试UI是否流畅</p>
          <input
            v-model.number="testValue"
            type="range"
            min="0"
            max="100"
            class="w-full mb-2"
          >
          <div class="text-center text-tech-accent text-2xl font-bold">{{ testValue }}</div>
        </div>
      </div>

      <!-- 图像处理演示 -->
      <div class="tech-card mb-8">
        <h2 class="text-2xl font-semibold mb-6 text-white">图像处理演示</h2>
        
        <div class="bg-gray-800 rounded-lg p-6">
          <div class="mb-4">
            <input
              ref="imageInputRef"
              type="file"
              accept="image/*"
              @change="loadImageForProcessing"
              class="hidden"
            >
            <button
              @click="imageInputRef?.click()"
              class="tech-button"
            >
              <i class="i-carbon-image mr-2"></i>
              选择图片
            </button>
          </div>

          <div v-if="hasImage" class="space-y-4">
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <h4 class="text-white font-semibold mb-2">原图</h4>
                <canvas
                  ref="originalCanvasRef"
                  class="border border-gray-700 rounded w-full"
                ></canvas>
              </div>
              <div>
                <h4 class="text-white font-semibold mb-2">处理后</h4>
                <canvas
                  ref="processedCanvasRef"
                  class="border border-gray-700 rounded w-full"
                ></canvas>
              </div>
            </div>

            <div class="flex flex-wrap gap-3">
              <button
                @click="processImageWithWorker('grayscale')"
                :disabled="isProcessingImage"
                class="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded transition-colors disabled:opacity-50"
              >
                灰度化
              </button>
              <button
                @click="processImageWithWorker('blur')"
                :disabled="isProcessingImage"
                class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded transition-colors disabled:opacity-50"
              >
                模糊
              </button>
              <button
                @click="processImageWithWorker('sharpen')"
                :disabled="isProcessingImage"
                class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded transition-colors disabled:opacity-50"
              >
                锐化
              </button>
              <button
                @click="processImageWithWorker('edge')"
                :disabled="isProcessingImage"
                class="bg-yellow-600 hover:bg-yellow-700 text-white px-4 py-2 rounded transition-colors disabled:opacity-50"
              >
                边缘检测
              </button>
            </div>

            <div v-if="processingTime" class="text-gray-400 text-sm">
              处理耗时: {{ processingTime }}ms
            </div>
          </div>
        </div>
      </div>

      <!-- 数据处理演示 -->
      <div class="tech-card mb-8">
        <h2 class="text-2xl font-semibold mb-6 text-white">大数据排序</h2>
        
        <div class="bg-gray-800 rounded-lg p-6">
          <div class="mb-4">
            <label class="text-white mr-3">数据量: {{ dataSize.toLocaleString() }}</label>
            <input
              v-model.number="dataSize"
              type="range"
              min="10000"
              max="1000000"
              step="10000"
              class="w-64"
            >
          </div>

          <div class="flex gap-3 mb-4">
            <button
              @click="sortWithWorker"
              :disabled="isSorting"
              class="tech-button disabled:opacity-50 disabled:cursor-not-allowed"
            >
              <i class="i-carbon-sorting mr-2"></i>
              {{ isSorting ? '排序中...' : '使用 Worker 排序' }}
            </button>
          </div>

          <div v-if="sortResult" class="space-y-2 text-gray-300">
            <div><strong>已排序:</strong> {{ sortResult.sorted.toLocaleString() }} 个数据</div>
            <div><strong>耗时:</strong> {{ sortResult.time }}ms</div>
            <div class="text-sm text-gray-400">
              前10个: [{{ sortResult.preview.join(', ') }}...]
            </div>
          </div>
        </div>
      </div>

      <!-- Worker 池演示 -->
      <div class="tech-card mb-8">
        <h2 class="text-2xl font-semibold mb-6 text-white">Worker 池并行处理</h2>
        
        <div class="bg-gray-800 rounded-lg p-6">
          <p class="text-gray-300 mb-4">
            使用多个 Worker 并行处理任务，充分利用多核CPU性能
          </p>
          
          <button
            @click="runParallelTasks"
            :disabled="isRunningParallel"
            class="tech-button mb-4 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            <i class="i-carbon-network-3 mr-2"></i>
            {{ isRunningParallel ? '处理中...' : '运行 8 个并行任务' }}
          </button>

          <div v-if="parallelResults.length > 0" class="space-y-2">
            <div
              v-for="(result, index) in parallelResults"
              :key="index"
              class="flex items-center gap-3 p-3 bg-gray-900 rounded"
            >
              <div class="flex-1">
                <span class="text-white">Worker {{ index + 1 }}</span>
              </div>
              <div class="text-gray-400 text-sm">{{ result.time }}ms</div>
              <div :class="result.done ? 'text-green-400' : 'text-yellow-400'">
                <i :class="result.done ? 'i-carbon-checkmark-filled' : 'i-carbon-in-progress'"></i>
              </div>
            </div>
            <div v-if="parallelTotalTime" class="text-tech-accent font-semibold mt-4">
              总耗时: {{ parallelTotalTime }}ms
            </div>
          </div>
        </div>
      </div>

      <!-- Shared Worker 演示 -->
      <div class="tech-card mb-8">
        <h2 class="text-2xl font-semibold mb-6 text-white">Shared Worker (共享)</h2>
        
        <div class="bg-gray-800 rounded-lg p-6">
          <div class="mb-4 p-4 bg-blue-900/30 border border-blue-600 rounded">
            <p class="text-blue-400 text-sm">
              <i class="i-carbon-information mr-2"></i>
              Shared Worker 可以在多个浏览器标签页之间共享。打开多个标签页查看效果。
            </p>
          </div>

          <div class="space-y-4">
            <div>
              <label class="text-white mb-2 block">发送消息:</label>
              <div class="flex gap-2">
                <input
                  v-model="sharedMessage"
                  type="text"
                  placeholder="输入消息..."
                  class="flex-1 bg-gray-900 text-white px-4 py-2 rounded border border-gray-700 focus:border-tech-accent outline-none"
                  @keyup.enter="sendToSharedWorker"
                >
                <button
                  @click="sendToSharedWorker"
                  class="tech-button"
                >
                  发送
                </button>
              </div>
            </div>

            <div v-if="sharedWorkerMessages.length > 0" class="space-y-2">
              <h4 class="text-white font-semibold">收到的消息:</h4>
              <div class="bg-gray-900 rounded p-4 max-h-48 overflow-y-auto">
                <div
                  v-for="(msg, index) in sharedWorkerMessages"
                  :key="index"
                  class="text-gray-300 text-sm mb-2"
                >
                  {{ msg }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- API 信息 -->
      <div class="tech-card">
        <h3 class="text-xl font-semibold mb-4 text-white">API 信息</h3>
        <div class="space-y-4 text-gray-300">
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">核心 API</h4>
            <ul class="list-disc list-inside space-y-1">
              <li><code class="bg-gray-800 px-2 py-1 rounded">new Worker(scriptURL)</code> - 创建专用Worker</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">worker.postMessage(data)</code> - 发送消息到Worker</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">worker.onmessage</code> - 接收Worker消息</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">worker.terminate()</code> - 终止Worker</li>
              <li><code class="bg-gray-800 px-2 py-1 rounded">new SharedWorker()</code> - 创建共享Worker</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">Worker 类型</h4>
            <ul class="list-disc list-inside space-y-1">
              <li><strong>Dedicated Worker:</strong> 只能被创建它的脚本访问</li>
              <li><strong>Shared Worker:</strong> 可以被多个脚本和标签页共享</li>
              <li><strong>Service Worker:</strong> 用于离线缓存和推送通知</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">使用场景</h4>
            <ul class="list-disc list-inside space-y-1">
              <li>复杂数学计算（如斐波那契、质数、加密）</li>
              <li>大数据处理（排序、过滤、搜索）</li>
              <li>图像和视频处理</li>
              <li>实时数据分析</li>
              <li>游戏物理引擎计算</li>
              <li>AI/ML 模型推理</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">限制</h4>
            <ul class="list-disc list-inside space-y-1 text-sm">
              <li>无法访问 DOM</li>
              <li>无法访问 window 对象</li>
              <li>无法直接操作父页面</li>
              <li>只能通过消息传递进行通信</li>
              <li>某些 Web API 不可用</li>
            </ul>
          </div>
          <div>
            <h4 class="font-semibold text-tech-accent mb-2">最佳实践</h4>
            <ul class="list-disc list-inside space-y-1 text-sm">
              <li>仅在必要时使用 Worker（有开销）</li>
              <li>使用 Worker 池来管理多个 Worker</li>
              <li>使用 Transferable Objects 来传输大数据</li>
              <li>及时终止不再使用的 Worker</li>
              <li>处理 Worker 错误事件</li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

// 性能对比
const isCalculating = ref(false)
const isWorkerCalculating = ref(false)
const mainThreadResult = ref<number | null>(null)
const workerResult = ref<number | null>(null)
const mainThreadTime = ref(0)
const workerTime = ref(0)
const testValue = ref(50)

// 图像处理
const imageInputRef = ref<HTMLInputElement>()
const originalCanvasRef = ref<HTMLCanvasElement>()
const processedCanvasRef = ref<HTMLCanvasElement>()
const hasImage = ref(false)
const isProcessingImage = ref(false)
const processingTime = ref(0)
let originalImageData: ImageData | null = null

// 数据排序
const dataSize = ref(100000)
const isSorting = ref(false)
const sortResult = ref<{ sorted: number; time: number; preview: number[] } | null>(null)

// 并行处理
const isRunningParallel = ref(false)
const parallelResults = ref<{ time: number; done: boolean }[]>([])
const parallelTotalTime = ref(0)

// Shared Worker
const sharedMessage = ref('')
const sharedWorkerMessages = ref<string[]>([])
let sharedWorker: SharedWorker | null = null

// === 性能对比 ===

const fibonacci = (n: number): number => {
  if (n <= 1) return n
  return fibonacci(n - 1) + fibonacci(n - 2)
}

const calculateOnMainThread = () => {
  isCalculating.value = true
  mainThreadResult.value = null
  
  setTimeout(() => {
    const start = performance.now()
    const result = fibonacci(42)
    const end = performance.now()
    
    mainThreadResult.value = result
    mainThreadTime.value = Math.round(end - start)
    isCalculating.value = false
  }, 10)
}

const calculateWithWorker = () => {
  isWorkerCalculating.value = true
  workerResult.value = null
  
  const workerScript = `
    const fibonacci = (n) => {
      if (n <= 1) return n
      return fibonacci(n - 1) + fibonacci(n - 2)
    }
    
    self.onmessage = function(e) {
      const start = performance.now()
      const result = fibonacci(e.data)
      const end = performance.now()
      self.postMessage({ result, time: end - start })
    }
  `
  
  const blob = new Blob([workerScript], { type: 'application/javascript' })
  const workerUrl = URL.createObjectURL(blob)
  const worker = new Worker(workerUrl)
  
  worker.onmessage = (e) => {
    workerResult.value = e.data.result
    workerTime.value = Math.round(e.data.time)
    isWorkerCalculating.value = false
    worker.terminate()
    URL.revokeObjectURL(workerUrl)
  }
  
  worker.onerror = (error) => {
    console.error('Worker error:', error)
    isWorkerCalculating.value = false
    worker.terminate()
    URL.revokeObjectURL(workerUrl)
  }
  
  worker.postMessage(42)
}

// === 图像处理 ===

const loadImageForProcessing = (e: Event) => {
  const target = e.target as HTMLInputElement
  const file = target.files?.[0]
  if (!file) return
  
  const reader = new FileReader()
  reader.onload = (event) => {
    const img = new Image()
    img.onload = () => {
      const originalCanvas = originalCanvasRef.value
      const processedCanvas = processedCanvasRef.value
      if (!originalCanvas || !processedCanvas) return
      
      // 设置画布大小
      originalCanvas.width = Math.min(img.width, 400)
      originalCanvas.height = Math.min(img.height, 300)
      processedCanvas.width = originalCanvas.width
      processedCanvas.height = originalCanvas.height
      
      const ctx = originalCanvas.getContext('2d')
      if (!ctx) return
      
      // 绘制原图
      ctx.drawImage(img, 0, 0, originalCanvas.width, originalCanvas.height)
      
      // 保存原始图像数据
      originalImageData = ctx.getImageData(0, 0, originalCanvas.width, originalCanvas.height)
      hasImage.value = true
    }
    img.src = event.target?.result as string
  }
  reader.readAsDataURL(file)
}

const processImageWithWorker = (filterType: string) => {
  if (!originalImageData) return
  
  isProcessingImage.value = true
  processingTime.value = 0
  
  const workerScript = `
    self.onmessage = function(e) {
      const { imageData, filterType } = e.data
      const data = imageData.data
      const start = performance.now()
      
      switch (filterType) {
        case 'grayscale':
          for (let i = 0; i < data.length; i += 4) {
            const avg = (data[i] + data[i + 1] + data[i + 2]) / 3
            data[i] = data[i + 1] = data[i + 2] = avg
          }
          break
          
        case 'blur':
          const tempData = new Uint8ClampedArray(data)
          const width = imageData.width
          const height = imageData.height
          for (let y = 1; y < height - 1; y++) {
            for (let x = 1; x < width - 1; x++) {
              for (let c = 0; c < 3; c++) {
                const idx = (y * width + x) * 4 + c
                let sum = 0
                for (let ky = -1; ky <= 1; ky++) {
                  for (let kx = -1; kx <= 1; kx++) {
                    sum += tempData[((y + ky) * width + (x + kx)) * 4 + c]
                  }
                }
                data[idx] = sum / 9
              }
            }
          }
          break
          
        case 'sharpen':
          const kernel = [0, -1, 0, -1, 5, -1, 0, -1, 0]
          const tempData2 = new Uint8ClampedArray(data)
          const width2 = imageData.width
          const height2 = imageData.height
          for (let y = 1; y < height2 - 1; y++) {
            for (let x = 1; x < width2 - 1; x++) {
              for (let c = 0; c < 3; c++) {
                let sum = 0
                for (let ky = -1; ky <= 1; ky++) {
                  for (let kx = -1; kx <= 1; kx++) {
                    const ki = (ky + 1) * 3 + (kx + 1)
                    sum += tempData2[((y + ky) * width2 + (x + kx)) * 4 + c] * kernel[ki]
                  }
                }
                data[(y * width2 + x) * 4 + c] = Math.min(255, Math.max(0, sum))
              }
            }
          }
          break
          
        case 'edge':
          const gx = [-1, 0, 1, -2, 0, 2, -1, 0, 1]
          const gy = [-1, -2, -1, 0, 0, 0, 1, 2, 1]
          const tempData3 = new Uint8ClampedArray(data)
          const width3 = imageData.width
          const height3 = imageData.height
          for (let y = 1; y < height3 - 1; y++) {
            for (let x = 1; x < width3 - 1; x++) {
              let sumX = 0, sumY = 0
              for (let ky = -1; ky <= 1; ky++) {
                for (let kx = -1; kx <= 1; kx++) {
                  const ki = (ky + 1) * 3 + (kx + 1)
                  const gray = tempData3[((y + ky) * width3 + (x + kx)) * 4]
                  sumX += gray * gx[ki]
                  sumY += gray * gy[ki]
                }
              }
              const magnitude = Math.sqrt(sumX * sumX + sumY * sumY)
              const idx = (y * width3 + x) * 4
              data[idx] = data[idx + 1] = data[idx + 2] = Math.min(255, magnitude)
            }
          }
          break
      }
      
      const end = performance.now()
      self.postMessage({ imageData, time: end - start })
    }
  `
  
  const blob = new Blob([workerScript], { type: 'application/javascript' })
  const workerUrl = URL.createObjectURL(blob)
  const worker = new Worker(workerUrl)
  
  const imageDataCopy = new ImageData(
    new Uint8ClampedArray(originalImageData.data),
    originalImageData.width,
    originalImageData.height
  )
  
  worker.onmessage = (e) => {
    const processedCanvas = processedCanvasRef.value
    if (!processedCanvas) return
    
    const ctx = processedCanvas.getContext('2d')
    if (!ctx) return
    
    ctx.putImageData(e.data.imageData, 0, 0)
    processingTime.value = Math.round(e.data.time)
    isProcessingImage.value = false
    worker.terminate()
    URL.revokeObjectURL(workerUrl)
  }
  
  worker.postMessage({ imageData: imageDataCopy, filterType })
}

// === 数据排序 ===

const sortWithWorker = () => {
  isSorting.value = true
  sortResult.value = null
  
  const workerScript = `
    self.onmessage = function(e) {
      const start = performance.now()
      const data = e.data
      data.sort((a, b) => a - b)
      const end = performance.now()
      
      self.postMessage({
        sorted: data.length,
        time: end - start,
        preview: data.slice(0, 10)
      })
    }
  `
  
  const blob = new Blob([workerScript], { type: 'application/javascript' })
  const workerUrl = URL.createObjectURL(blob)
  const worker = new Worker(workerUrl)
  
  // 生成随机数据
  const data = Array.from({ length: dataSize.value }, () => Math.floor(Math.random() * 1000000))
  
  worker.onmessage = (e) => {
    sortResult.value = {
      sorted: e.data.sorted,
      time: Math.round(e.data.time),
      preview: e.data.preview
    }
    isSorting.value = false
    worker.terminate()
    URL.revokeObjectURL(workerUrl)
  }
  
  worker.postMessage(data)
}

// === 并行处理 ===

const runParallelTasks = async () => {
  isRunningParallel.value = true
  parallelResults.value = []
  parallelTotalTime.value = 0
  
  const workerScript = `
    self.onmessage = function(e) {
      const start = performance.now()
      
      // 模拟耗时计算
      const fibonacci = (n) => {
        if (n <= 1) return n
        return fibonacci(n - 1) + fibonacci(n - 2)
      }
      
      const result = fibonacci(40)
      const end = performance.now()
      
      self.postMessage({ result, time: end - start })
    }
  `
  
  const startTime = performance.now()
  const workerCount = 8
  const workers: Worker[] = []
  
  // 初始化结果数组
  for (let i = 0; i < workerCount; i++) {
    parallelResults.value.push({ time: 0, done: false })
  }
  
  const promises = Array.from({ length: workerCount }, (_, index) => {
    return new Promise<void>((resolve) => {
      const blob = new Blob([workerScript], { type: 'application/javascript' })
      const workerUrl = URL.createObjectURL(blob)
      const worker = new Worker(workerUrl)
      workers.push(worker)
      
      worker.onmessage = (e) => {
        parallelResults.value[index] = {
          time: Math.round(e.data.time),
          done: true
        }
        worker.terminate()
        URL.revokeObjectURL(workerUrl)
        resolve()
      }
      
      worker.postMessage(null)
    })
  })
  
  await Promise.all(promises)
  
  const endTime = performance.now()
  parallelTotalTime.value = Math.round(endTime - startTime)
  isRunningParallel.value = false
}

// === Shared Worker ===

const initSharedWorker = () => {
  if (sharedWorker) return
  
  try {
    const workerScript = `
      const connections = []
      
      self.onconnect = function(e) {
        const port = e.ports[0]
        connections.push(port)
        
        port.onmessage = function(event) {
          // 广播消息给所有连接
          connections.forEach(p => {
            p.postMessage('收到消息: ' + event.data)
          })
        }
        
        port.start()
        port.postMessage('已连接到 Shared Worker')
      }
    `
    
    const blob = new Blob([workerScript], { type: 'application/javascript' })
    const workerUrl = URL.createObjectURL(blob)
    sharedWorker = new SharedWorker(workerUrl)
    
    sharedWorker.port.onmessage = (e) => {
      sharedWorkerMessages.value.push(e.data)
    }
    
    sharedWorker.port.start()
  } catch (error) {
    console.error('Shared Worker not supported:', error)
    sharedWorkerMessages.value.push('浏览器不支持 Shared Worker')
  }
}

const sendToSharedWorker = () => {
  if (!sharedMessage.value.trim()) return
  
  if (!sharedWorker) {
    initSharedWorker()
  }
  
  sharedWorker?.port.postMessage(sharedMessage.value)
  sharedMessage.value = ''
}

// 初始化 Shared Worker
initSharedWorker()
</script>

<style scoped>
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  cursor: pointer;
}

input[type="range"]::-webkit-slider-track {
  background: #374151;
  height: 0.5rem;
  border-radius: 0.25rem;
}

input[type="range"]::-moz-range-track {
  background: #374151;
  height: 0.5rem;
  border-radius: 0.25rem;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: #3b82f6;
  cursor: pointer;
  margin-top: -0.375rem;
}

input[type="range"]::-moz-range-thumb {
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: #3b82f6;
  cursor: pointer;
  border: none;
}
</style>
